package com.cy.pj.sys.service.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Order(0)
@Aspect
@Component
public class SysTimeAspect {

    @Pointcut("@annotation(com.cy.pj.sys.common.annotation.RequiredTime)")
    public void doTime(){

    }
    //目标方法执行前调用,通常会在@Before方法中做一些数据过滤或预处理
    //所有非@Around通知方法中可以使用JoinPoint作为连接点参数
    @Before("doTime()")
    public void doBefore(){
        System.out.println("@Before");
    }
    //

    /**
     * 无论异常还是正常结束都会执行
     * 通常会在@After描述的方法中进行一些资源释放操作
     */
    @After("doTime()")
    public void doAfter(){
        System.out.println("@After");
    }
    //目标方法正常结束时执行,可以在这样的方法进行缓存更新操作(清除-cache.clear(),更新)
    @AfterReturning("doTime()")
    public void doAfterReturning(){
        System.out.println("@AfterReturning");
    }
    //目标方法出现异常时执行,可以在此方法中,可以进行错误日志的纪录,可以报警,发送邮件,发送短信
    @AfterThrowing("doTime()")
    public void doAfterThrowing(){
        System.out.println("@AfterThrowing");
    }

    //环绕通知,优先级最高

    /**
     * @Around 描述的方法可以在内部通过连接点对象,手动调用目标方法
     * @param joinPoint 连接点对象,@Around描述的方法只能应用ProceedingJoinPoint
     * @return 目标业务的执行结果
     * @throws Throwable
     */
    @Around("doTime()")
    public Object doAround(ProceedingJoinPoint joinPoint)
        throws  Throwable{
        System.out.println("SysTimeAspect开始执行了");
        try{
            System.out.println("@Around.before");
            //本类其他before,其他切面的before,目标方法,当前或其他切面的后续通知方法
            Object result = joinPoint.proceed();
            System.out.println("@Around.AfterReturning");
            return result;
        }catch (Exception e){
            System.out.println("@Around AfterThrowing");
            e.printStackTrace();
            throw e;
        }finally {
            System.out.println("@Around.after");
            System.out.println("SysTimeAspect执行结束了");
        }
    }
}
